
#include "LayerManagerEX.h"
#include <stdlib.h>

LAYERGROUP::LAYERGROUP(int width, int height):
    lm(width, height)
{
}

LayerManagerEX::LayerManagerEX(int width, int height):
    m_pTopGroup(0),
    m_pBottomGroup(0),
    m_nNumberOfGroups(1),
    m_pAvailableSlot(1),
    m_nNumberOfInvRegions(0),
    m_nGid(0),
    m_stDefaultGroup(width, height)
{
    int i;
    Region empReg;
    empReg.left=0;
    empReg.top=0;
    empReg.right=0;
    empReg.bottom=0;
    m_nScreenWidth = width;
    m_nScreenHeight = height;

    for (i=0; i<MaxNumGroup; i++) {
        m_pGroup[i] = 0;
    }

    for (i=0; i<MaxNumInvReg; i++) {
        m_aInvalidRegion[i] = empReg;
    }

    m_pGroup[0] = &m_stDefaultGroup;
    m_pBottomGroup = m_pGroup[0];
    m_pTopGroup = m_pGroup[0];

    m_pGroup[0]->Position.x = 0;
    m_pGroup[0]->Position.y = 0;
    m_pGroup[0]->nIndex = 0;
    m_pGroup[0]->pPrevGroup = 0;
    m_pGroup[0]->pNextGroup = 0;
    m_pGroup[0]->bEnable = true;
    m_pGroup[0]->ClippingRegion.left = 0;
    m_pGroup[0]->ClippingRegion.top = 0;
    m_pGroup[0]->ClippingRegion.right = 0;
    m_pGroup[0]->ClippingRegion.bottom = 0;
}

LayerManagerEX::~LayerManagerEX()
{
    int i=1;
    while (m_nNumberOfGroups > 1 && i < MaxNumGroup)
    {
        if (m_pGroup[i]) {
            delete  m_pGroup[i];
            m_pGroup[i] = 0;
            m_nNumberOfGroups--;
        }
        i++;
    }
}

bool LayerManagerEX::MergeIntersection(int left, int top, int right, int bottom, int id)
{
    int minx, miny, maxx, maxy, mtx, mty, mbx, mby;

    if (m_aInvalidRegion[id].left>left) {
        minx = m_aInvalidRegion[id].left;
        mtx = left;
    }
    else {
        mtx = m_aInvalidRegion[id].left;
        minx = left;
    }

    if (m_aInvalidRegion[id].top>top) {
        miny = m_aInvalidRegion[id].top;
        mty = top;
    }
    else {
        mty = m_aInvalidRegion[id].top;
        miny = top;
    }

    if (m_aInvalidRegion[id].right<right) {
        maxx = m_aInvalidRegion[id].right;
        mbx = right;
    }
    else {
        mbx = m_aInvalidRegion[id].right;
        maxx = right;
    }

    if (m_aInvalidRegion[id].bottom<bottom) {
        maxy = m_aInvalidRegion[id].bottom;
        mby = bottom;
    }
    else {
        mby = m_aInvalidRegion[id].bottom;
        maxy = bottom;
    }

    if ((minx > maxx) || (miny > maxy)) {
        return false;
    }
    else {
        m_aInvalidRegion[id].left = mtx;
        m_aInvalidRegion[id].top = mty;
        m_aInvalidRegion[id].right = mbx;
        m_aInvalidRegion[id].bottom = mby;
        return true;
    }
}

void LayerManagerEX::AddInvalidRegion(Region invreg)
{
    int i =0;
    int merged = 0;

    if (m_nNumberOfInvRegions > 0) {
        while (i < m_nNumberOfInvRegions) {
            if (MergeIntersection(invreg.left, invreg.top, invreg.right, invreg.bottom, i)) {
                merged = 1;
                return;
            }
            i++;
        }
        if (MaxNumInvReg == i) {
            m_aInvalidRegion[i].left = min(m_aInvalidRegion[i].left, invreg.left);
            m_aInvalidRegion[i].top = min(m_aInvalidRegion[i].top, invreg.top);
            m_aInvalidRegion[i].right = max(m_aInvalidRegion[i].right, invreg.right);
            m_aInvalidRegion[i].bottom = max(m_aInvalidRegion[i].bottom, invreg.bottom);
            merged = 1;
        }
        if (!merged) {
            m_aInvalidRegion[i].left = invreg.left;
            m_aInvalidRegion[i].top = invreg.top;
            m_aInvalidRegion[i].right = invreg.right;
            m_aInvalidRegion[i].bottom = invreg.bottom;
            m_nNumberOfInvRegions++;
        }
    }
    else {
        m_aInvalidRegion[0].left = invreg.left;
        m_aInvalidRegion[0].top = invreg.top;
        m_aInvalidRegion[0].right = invreg.right;
        m_aInvalidRegion[0].bottom = invreg.bottom;
        m_nNumberOfInvRegions = 1;
    }
}

void LayerManagerEX::AddInvalidRegion(int left, int top, int right, int bottom)
{

    int i =0;
    int merged = 0;

    if (m_nNumberOfInvRegions > 0) {
        while (i < m_nNumberOfInvRegions) {
            if (MergeIntersection(left, top, right, bottom, i)) {
                merged = 1;
                break;
            }
            i++;
        }
        if (MaxNumInvReg == i) {
            m_aInvalidRegion[i].left = min(m_aInvalidRegion[i].left, left);
            m_aInvalidRegion[i].top = min(m_aInvalidRegion[i].top, top);
            m_aInvalidRegion[i].right = max(m_aInvalidRegion[i].right, right);
            m_aInvalidRegion[i].bottom = max(m_aInvalidRegion[i].bottom, bottom);
            merged = 1;
        }
        if (!merged) {
            m_aInvalidRegion[i].left = left;
            m_aInvalidRegion[i].top = top;
            m_aInvalidRegion[i].right = right;
            m_aInvalidRegion[i].bottom = bottom;
            m_nNumberOfInvRegions++;
        }
    }
    else {
        m_aInvalidRegion[0].left = left;
        m_aInvalidRegion[0].top = top;
        m_aInvalidRegion[0].right = right;
        m_aInvalidRegion[0].bottom = bottom;
        m_nNumberOfInvRegions = 1;
    }
}

int LayerManagerEX::AddLayer(BitmapBufInfo & img, int x, int y, int level)
{
    Region reg;
    int lid = -1;
    if (m_pGroup[m_nGid]) {
        lid = m_pGroup[m_nGid]->lm.AddLayer(img, x, y, level);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(lid,&reg))
            AddInvalidRegion(reg);
    }
    return lid;
}


void LayerManagerEX::EnableAllGroups()
{
    int i=0;
    int numberOfGroups = m_nNumberOfGroups;
    while (numberOfGroups > 0 && i < MaxNumGroup)
    {
        if (m_pGroup[i]) {
            m_pGroup[i]->bEnable = 1;
            numberOfGroups--;
        }
        i++;
    }
    AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);
}

void LayerManagerEX::DisableAllGroups()
{
    int i=0;
    int numberOfGroups = m_nNumberOfGroups;
    while (numberOfGroups > 0 && i < MaxNumGroup)
    {
        if (m_pGroup[i]) {
            m_pGroup[i]->bEnable = 0;
            numberOfGroups--;
        }
        i++;
    }
    AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);
}

void LayerManagerEX::EnableGroupByIndex(int index)
{
    if (!m_pGroup[index]) return;
    else m_pGroup[index]->bEnable = 1;
    AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);
}

void LayerManagerEX::DisableGroupByIndex(int index)
{
    if (!m_pGroup[index]) return;
    else m_pGroup[index]->bEnable = 0;
    AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);
}

void LayerManagerEX::RemoveAllGroups()
{
    int i=1;
    while (m_nNumberOfGroups > 1 && i < MaxNumGroup)
    {
        if (m_pGroup[i]) {
            delete  m_pGroup[i];
            m_pGroup[i] = 0;
            m_nNumberOfGroups--;
        }
        i++;
    }
    AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);
}

int LayerManagerEX::RemoveGroupByIndex(int index)
{
    if (!m_pGroup[index]) return -1;

    if (m_pGroup[index] == m_pBottomGroup) {
        if (m_pTopGroup == m_pBottomGroup) {
            m_pBottomGroup = 0;
            m_pTopGroup = 0;
        }
        else {
            m_pGroup[index]->pNextGroup->pPrevGroup = 0;
            m_pBottomGroup = m_pGroup[index]->pNextGroup;
        }
    }
    else if (m_pGroup[index] == m_pTopGroup) {
        if (m_pTopGroup == m_pBottomGroup) {
            m_pTopGroup = 0;
            m_pBottomGroup = 0;
        }
        else {
            m_pTopGroup = m_pGroup[index]->pPrevGroup;
            m_pGroup[index]->pPrevGroup->pNextGroup = 0;
        }
    }
    else {
        m_pGroup[index]->pPrevGroup->pNextGroup = m_pGroup[index]->pNextGroup;
        m_pGroup[index]->pNextGroup->pPrevGroup = m_pGroup[index]->pPrevGroup;
    }


    delete m_pGroup[index];
    m_pGroup[index] = 0;

    if (m_pAvailableSlot > index)
        m_pAvailableSlot = index;

    m_nNumberOfGroups--;
    AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);

    return index;
}

int LayerManagerEX::GroupBringForward(int index)
{
    LAYERGROUP * temp;
    if (!m_pGroup[index]) return -1;

    if (m_pTopGroup == m_pBottomGroup) {
        return index;
    }

    if (m_pGroup[index] == m_pTopGroup) {
        return index;
    }

    temp = m_pGroup[index]->pNextGroup;

    if (temp->pNextGroup)
        temp->pNextGroup->pPrevGroup = m_pGroup[index];
    if (m_pGroup[index]->pPrevGroup)
        m_pGroup[index]->pPrevGroup->pNextGroup = temp;

    m_pGroup[index]->pNextGroup = temp->pNextGroup;
    temp->pNextGroup = m_pGroup[index];
    temp->pPrevGroup = m_pGroup[index]->pPrevGroup;
    m_pGroup[index]->pPrevGroup = temp;

    if (m_pBottomGroup == m_pGroup[index]) m_pBottomGroup = temp;
    if (m_pTopGroup == temp) m_pTopGroup = m_pGroup[index];

    AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);

    return index;
}

int LayerManagerEX::GroupSendBackward(int index)
{
    LAYERGROUP * temp;
    if (!m_pGroup[index]) return -1;

    if (m_pTopGroup == m_pBottomGroup) {
        return index;
    }

    if (m_pGroup[index] == m_pBottomGroup) {
        return index;
    }

    temp = m_pGroup[index]->pPrevGroup;

    if (temp->pPrevGroup)
        temp->pPrevGroup->pNextGroup = m_pGroup[index];
    if (m_pGroup[index]->pNextGroup )
        m_pGroup[index]->pNextGroup->pPrevGroup = temp;

    m_pGroup[index]->pPrevGroup = temp->pPrevGroup;
    temp->pPrevGroup = m_pGroup[index];
    temp->pNextGroup = m_pGroup[index]->pNextGroup;
    m_pGroup[index]->pNextGroup = temp;

    if (m_pTopGroup == m_pGroup[index]) m_pTopGroup = temp;
    if (m_pBottomGroup == temp) m_pBottomGroup = m_pGroup[index];

    AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);

    return index;
}

int LayerManagerEX::GroupBringToFront(int index)
{

    if (!m_pGroup[index]) return -1;
    if (m_pTopGroup == m_pBottomGroup) {
        return index;
    }
    if (m_pGroup[index] == m_pTopGroup) {
        return index;
    }

    if (m_pBottomGroup == m_pGroup[index])
        m_pBottomGroup = m_pGroup[index]->pNextGroup;

    m_pTopGroup->pNextGroup = m_pGroup[index];
    m_pGroup[index]->pNextGroup->pPrevGroup =  m_pGroup[index]->pPrevGroup;

    if (m_pGroup[index]->pPrevGroup)
        m_pGroup[index]->pPrevGroup->pNextGroup = m_pGroup[index]->pNextGroup;

    m_pGroup[index]->pNextGroup = 0;
    m_pGroup[index]->pPrevGroup = m_pTopGroup;
    m_pTopGroup = m_pGroup[index];

    AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);

    return index;
}

int LayerManagerEX::GroupSendToBack(int index)
{
    if (!m_pGroup[index]) return -1;
    if (m_pTopGroup == m_pBottomGroup) {
        return index;
    }
    if (m_pGroup[index] == m_pBottomGroup) {
        return index;
    }

    if (m_pTopGroup == m_pGroup[index])
        m_pTopGroup = m_pGroup[index]->pPrevGroup;

    m_pBottomGroup->pPrevGroup = m_pGroup[index];
    m_pGroup[index]->pPrevGroup->pNextGroup =  m_pGroup[index]->pNextGroup;

    if (m_pGroup[index]->pNextGroup)
        m_pGroup[index]->pNextGroup->pPrevGroup = m_pGroup[index]->pPrevGroup;

    m_pGroup[index]->pPrevGroup = 0;
    m_pGroup[index]->pNextGroup = m_pBottomGroup;
    m_pBottomGroup = m_pGroup[index];

    AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);

    return index;
}

int LayerManagerEX::CreateNewGroup()
{
    int temp = m_pAvailableSlot;
    if ((m_nNumberOfGroups + 1) >= MaxNumGroup) return -1;
    m_pGroup[m_pAvailableSlot] = new LAYERGROUP(m_nScreenWidth, m_nScreenHeight);
    if (!m_pGroup[m_pAvailableSlot]) return -1;
    if (!m_pBottomGroup) m_pBottomGroup = m_pGroup[m_pAvailableSlot];

    m_pGroup[m_pAvailableSlot]->Position.x = 0;
    m_pGroup[m_pAvailableSlot]->Position.y = 0;
    m_pGroup[m_pAvailableSlot]->nIndex = m_pAvailableSlot;
    m_pGroup[m_pAvailableSlot]->pPrevGroup = m_pTopGroup;
    m_pGroup[m_pAvailableSlot]->pNextGroup = 0;
    m_pGroup[m_pAvailableSlot]->bEnable = true;
    m_pGroup[m_pAvailableSlot]->ClippingRegion.left = 0;
    m_pGroup[m_pAvailableSlot]->ClippingRegion.top = 0;
    m_pGroup[m_pAvailableSlot]->ClippingRegion.right = 0;
    m_pGroup[m_pAvailableSlot]->ClippingRegion.bottom = 0;

    if (m_pTopGroup) m_pTopGroup->pNextGroup = m_pGroup[m_pAvailableSlot];

    m_pTopGroup = m_pGroup[m_pAvailableSlot];
    while (m_pGroup[m_pAvailableSlot] != 0) m_pAvailableSlot++;
    m_nNumberOfGroups++;

    return temp;
}

void LayerManagerEX::SelectGroup(int index)
{
    m_nGid = index;
}

int  LayerManagerEX::LayerBringForward(int index)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index, &reg))
            AddInvalidRegion(reg);
        return m_pGroup[m_nGid]->lm.LayerBringForward(index);
    }
    else return -1;
}

int  LayerManagerEX::LayerSendBackward(int index)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        return m_pGroup[m_nGid]->lm.LayerSendBackward(index);
    }
    else return -1;
}

int  LayerManagerEX::LayerBringToFront(int index)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        return m_pGroup[m_nGid]->lm.LayerBringToFront(index);
    }
    else return -1;
}

int  LayerManagerEX::LayerSendToBack(int index)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        return m_pGroup[m_nGid]->lm.LayerSendToBack(index);
    }
    else return -1;
}

void LayerManagerEX::LayerRestore(int index)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.LayerRestore(index);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
    }
}

void LayerManagerEX::LayerFlip(int index, int direction)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.LayerFlip(index, direction);
    }
}

int  LayerManagerEX::RemoveLayerByIndex(int index)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        return m_pGroup[m_nGid]->lm.RemoveLayerByIndex(index);
    }
    else return -1;
}

void LayerManagerEX::RemoveAllLayers()
{
    if (m_pGroup[m_nGid]) {
        AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);
        m_pGroup[m_nGid]->lm.RemoveAllLayers();
    }
}

int  LayerManagerEX::DuplicateLayer(int index, int xin, int yin, int level, int style)
{
    int id = -1;
    if (m_pGroup[m_nGid]) {
        id = m_pGroup[m_nGid]->lm.DuplicateLayer(index, xin, yin, level, style);
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(id,&reg))
            AddInvalidRegion(reg);
        return id;
    }
    else return id;
}

int  LayerManagerEX::LayerResize(int index, int width, int height)
{
    int flag = -1;
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        flag = m_pGroup[m_nGid]->lm.LayerResize(index, width, height);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        return flag;
    }
    else return -1;
}

void  LayerManagerEX::ForceLayerInvalidRegion(int index)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
    }
    return;
}

int  LayerManagerEX::LayerRotate90(int index, int times)
{
    int flag = -1;
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        flag =  m_pGroup[m_nGid]->lm.LayerRotate90(index, times);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        return flag;
    }
    else return -1;
}

void LayerManagerEX::SetLayerTransparency(int index, int level)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.SetLayerTransparency(index, level);
    }
}

int  LayerManagerEX::GetLayerTransparency(int index)
{
    if (m_pGroup[m_nGid]) {
        return m_pGroup[m_nGid]->lm.GetLayerTransparency(index);
    }
    else return -1;
}

int LayerManagerEX::GetNumberOfGroups()
{
    return m_nNumberOfGroups;
}

void LayerManagerEX::ShowLayer(int index, bool visible)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.ShowLayer(index, visible);
    }
}

void LayerManagerEX::MoveLayer(int index, int x, int y)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.MoveLayer(index, x, y);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);

    }
}

void LayerManagerEX::SetLayerPosition(int index, int x, int y)
{
//    DebugBreak();
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.SetLayerPosition(index, x, y);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
    }
}

void LayerManagerEX::SetLayerBlendType(int index, int type)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.SetLayerBlendType(index, type);
    }
}

void LayerManagerEX::SetLayerColor(int index, unsigned char R, unsigned char G, unsigned char B)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.SetLayerColor(index, R, G, B);
    }
}

int  LayerManagerEX::GetLayerType(int index)
{
    if (m_pGroup[m_nGid]) {
        return m_pGroup[m_nGid]->lm.GetLayerType(index);
    }
    else return -1;
}

void LayerManagerEX::SetBackgroundColor(unsigned char R, unsigned char G, unsigned char B)
{
    if (m_pGroup[m_nGid]) {
        AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);
        m_pGroup[m_nGid]->lm.SetBackgroundColor(R, G, B);
    }
}

void LayerManagerEX::StretchLayer(int index, int StretchX, int StretchY)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.StretchLayer(index, StretchX, StretchY);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
    }
}

void LayerManagerEX::ResizeLayer(int index, int StretchX, int StretchY, int alignX, int alignY)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.ResizeLayer(index, StretchX, StretchY, alignX, alignY);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
    }
}

int  LayerManagerEX::WarpLayerLR(int index, int StretchX, int StretchYL, int StretchYR)
{
    int flag;
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        flag = m_pGroup[m_nGid]->lm.WarpLayerLR(index, StretchX, StretchYL, StretchYR);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        return flag;
    }
    else return -1;
}

int  LayerManagerEX::WarpLayerTD(int index, int StretchY, int StretchXT, int StretchXD)
{
    int flag;
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        flag = m_pGroup[m_nGid]->lm.WarpLayerTD(index, StretchY, StretchXT, StretchXD);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        return flag;
    }
    else return -1;
}

int  LayerManagerEX::ShearLayer(int index, int offset, int StretchX, int StretchY)
{
    int flag;
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        flag = m_pGroup[m_nGid]->lm.ShearLayer(index, offset, StretchX, StretchY);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        return flag;
    }
    else return -1;
}

int  LayerManagerEX::WaveLayer(int index, int* aSampleX16, int width, int height, int InnerWidth)
{
    int flag;
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        flag = m_pGroup[m_nGid]->lm.WaveLayer(index, aSampleX16, width, height, InnerWidth);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        return flag;
    }
    else return -1;
}

int  LayerManagerEX::MergeLayer(int SrcIndex, int DstIndex)
{
    int flag;
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(SrcIndex,&reg))
            AddInvalidRegion(reg);
        flag = m_pGroup[m_nGid]->lm.MergeLayer(SrcIndex, DstIndex);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(DstIndex,&reg))
            AddInvalidRegion(reg);
        return flag;
    }
    else return -1;
}

void LayerManagerEX::SetViewPosition(int x, int y)
{
    if (m_pGroup[m_nGid]) {
        m_pGroup[m_nGid]->lm.SetViewPosition(x, y);
    }
}

void LayerManagerEX::IsTransparent(bool flag)
{
    if (m_pGroup[m_nGid]) {
        AddInvalidRegion(0, 0, m_nScreenWidth, m_nScreenHeight);
        m_pGroup[m_nGid]->lm.IsTransparent(flag);
    }
}

void LayerManagerEX::ZoomLayer(int index, float zoomlevel)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.ZoomLayer(index, zoomlevel);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
    }
}

void LayerManagerEX::ZoomLayerByPoint(int index, float zoomlevel, int x, int y)
{
    if (m_pGroup[m_nGid]) {
        Region reg;
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
        m_pGroup[m_nGid]->lm.ZoomLayerByPoint(index, zoomlevel, x ,y);
        if (m_pGroup[m_nGid]->lm.GetLayerVisibleRegion(index,&reg))
            AddInvalidRegion(reg);
    }
}

Point* LayerManagerEX::GetLayerPosition(int index)
{
    if (m_pGroup[m_nGid]) {
        return m_pGroup[m_nGid]->lm.GetLayerPosition(index);
    }
    else return 0;
}

BitmapBufInfo*    LayerManagerEX::GetLayerBits(int index)
{
    if (m_pGroup[m_nGid]) {
        return m_pGroup[m_nGid]->lm.GetLayerBits(index);
    }
    else return 0;
}

Layer*    LayerManagerEX::GetLayerInfo(int index)
{
    if (m_pGroup[m_nGid]) {
        return m_pGroup[m_nGid]->lm.GetLayerInfo(index);
    }
    else return 0;
}

BitmapBufInfo*    LayerManagerEX::GetSrcLayerBits(int index)
{
    if (m_pGroup[m_nGid]) {
        return m_pGroup[m_nGid]->lm.GetSrcLayerBits(index);
    }
    else return 0;
}

void LayerManagerEX::RenderToBuffer(BitmapBufInfo & img, int OffsetX, int OffsetY,
                                int RenderLen,
                                int RenderHt)
{

    int minx, miny, maxx, maxy, left, top, right, bottom, i;
    LAYERGROUP * TempPTR = m_pBottomGroup;

    while (TempPTR) {
        if (TempPTR->bEnable) {
            i = 0;
            while (i<m_nNumberOfInvRegions) {
                if (TempPTR->ClippingRegion.left - TempPTR->ClippingRegion.right) {
                    left = TempPTR->ClippingRegion.left;
                    right = TempPTR->ClippingRegion.right;
                    top = TempPTR->ClippingRegion.top;
                    bottom = TempPTR->ClippingRegion.bottom;
                }
                else {
                    left = OffsetX;
                    top = OffsetY;
                    right = OffsetX+RenderLen;
                    bottom = OffsetY+RenderHt;
                }
                minx = max(left, m_aInvalidRegion[i].left);
                miny = max(top, m_aInvalidRegion[i].top);
                maxx = min(right, m_aInvalidRegion[i].right);
                maxy = min(bottom, m_aInvalidRegion[i].bottom);

                if ((minx<maxx) && (miny < maxy)) {
                    TempPTR->lm.SetViewPosition(minx, miny);
                    TempPTR->lm.RenderToBuffer(img, minx, miny,
                                               maxx - minx, maxy - miny);
                }
                i++;
            }
        }
        TempPTR = TempPTR->pNextGroup;
    }
    m_nNumberOfInvRegions = 0;
}

void LayerManagerEX::SetClippingRegion(int left, int top, int right, int bottom)
{
    if (m_pGroup[m_nGid]) {
        m_pGroup[m_nGid]->ClippingRegion.left = left;
        m_pGroup[m_nGid]->ClippingRegion.top = top;
        m_pGroup[m_nGid]->ClippingRegion.right = right;
        m_pGroup[m_nGid]->ClippingRegion.bottom = bottom;
    }
}

void LayerManagerEX::SetScreenSize(int width, int height)
{
    m_nScreenWidth = width;
    m_nScreenHeight = height;
    m_nNumberOfInvRegions = 0;

    int nNumberOfGroups = m_nNumberOfGroups;
    int i = 0;
    while (nNumberOfGroups > 0 && i < MaxNumGroup)
    {
        if (m_pGroup[i]) {
            m_pGroup[i]->lm.SetScreenSize(width, height);
            nNumberOfGroups--;
        }
        i++;
    }
}

void LayerManagerEX::ClearClippingRegion()
{
    if (m_pGroup[m_nGid]) {
        m_pGroup[m_nGid]->ClippingRegion.left = 0;
        m_pGroup[m_nGid]->ClippingRegion.top = 0;
        m_pGroup[m_nGid]->ClippingRegion.right = 0;
        m_pGroup[m_nGid]->ClippingRegion.bottom = 0;
    }
}

LayerManager* LayerManagerEX::GetGroupLayerManager(int m_nGid)
{
    if (m_pGroup[m_nGid])
        return &m_pGroup[m_nGid]->lm;
    else return 0;
}

int LayerManagerEX::GetAllLayerIds(int* pid)
{
    if (m_pGroup[m_nGid]) {
       return m_pGroup[m_nGid]->lm.GetAllLayerIds(pid);
    }
    else return 0;
}

int LayerManagerEX::GetNumberOfLayers()
{
    if (m_pGroup[m_nGid]) {
       return m_pGroup[m_nGid]->lm.GetNumberOfLayers();
    }
    else return 0;
}

int LayerManagerEX::GetInvalidRegionNum()
{
    return m_nNumberOfInvRegions;
}

void LayerManagerEX::GetInvalidRegion(int id, int* left, int* top, int* right, int* bottom)
{
    *left = m_aInvalidRegion[id].left;
    *top = m_aInvalidRegion[id].top;
    *right = m_aInvalidRegion[id].right;
    *bottom = m_aInvalidRegion[id].bottom;
}



